package com.geekteam.manga.rest;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;

import com.geekteam.manga.Utils.LogUtils;

public class RestCaller implements IRESTCall {
	private ArrayList<NameValuePair> params;
	private ArrayList<NameValuePair> headers;
	private String url;
	private int responseCode;
	private String message;
	private static final String TAG = LogUtils.makeLogTag(RestCaller.class);

	public String getErrorMessage() {
		return message;
	}

	public int getResponseCode() {
		return responseCode;
	}

	public RestCaller(String url, String token) {
		this.url = url;
		params = new ArrayList<NameValuePair>();
		headers = new ArrayList<NameValuePair>();
		addParam("token", token);
	}

	public void addParam(String name, String value) {
		params.add(new BasicNameValuePair(name, value));
	}

	public void addHeader(String name, String value) {
		headers.add(new BasicNameValuePair(name, value));
	}

	public String execute(String methodName) throws Exception {
		HttpPost request = new HttpPost(url + "/" + methodName);

		// add headers
		for (NameValuePair h : headers) {
			request.addHeader(h.getName(), h.getValue());
		}

		if (!params.isEmpty()) {
			request.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
		}

		return executeRequest(request);

	}

	private String executeRequest(HttpUriRequest request) {

		HttpResponse httpResponse;
		String response = null;
		
		HttpParams httpParameters = new BasicHttpParams();
		int timeoutConnection = 10000;//set time out 10s
		HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
		int timeoutSocket = 5000;//socket time out 5s
		HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
		
		HttpClient client = new DefaultHttpClient(httpParameters);

		try {
			httpResponse = client.execute(request);
			responseCode = httpResponse.getStatusLine().getStatusCode();
			message = httpResponse.getStatusLine().getReasonPhrase();

			HttpEntity entity = httpResponse.getEntity();

			if (entity != null) {

				InputStream instream = entity.getContent();
				response = convertStreamToString(instream);

				// Closing the input stream will trigger connection release
				instream.close();
			}

		} catch (ClientProtocolException e) {
			client.getConnectionManager().shutdown();
			e.printStackTrace();
			response = null;
		} catch (IOException e) {
			client.getConnectionManager().shutdown();
			e.printStackTrace();
			response = null;
		}

		return response;
	}

	private static String convertStreamToString(InputStream is) {

		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		StringBuilder sb = new StringBuilder();

		String line = null;
		try {
			if ((line = reader.readLine()) != null) {
				sb.append(line);
			}
			while ((line = reader.readLine()) != null) {
				sb.append("\n" + line);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return sb.toString();
	}

	public static String excute(String url,
			ArrayList<ParcelableNameValuePair> parcelableNameValuePair) {
		if(parcelableNameValuePair ==null){
			parcelableNameValuePair = new ArrayList<ParcelableNameValuePair>();
		}

		DefaultHttpClient httpClient = getThreadSafeClient();
		HttpPost httpPost = new HttpPost(url);
		LogUtils.LOGI(TAG, url);
		String result = null;
		HttpEntity entity = null;

		try {
			UrlEncodedFormEntity FormEntity = new UrlEncodedFormEntity(
					parcelableNameValuePair, HTTP.UTF_8);
			httpPost.setEntity(FormEntity);
			HttpResponse response = httpClient.execute(httpPost);
			entity = response.getEntity();
			if (entity != null) {
				InputStream instream = entity.getContent();
				result = convertStreamToString(instream);
				int startSub = result.indexOf("{");
				if (startSub > 0) {
					result = result.substring(startSub);
				}
				instream.close();
			}
			entity.consumeContent();
			httpClient.getConnectionManager().shutdown();
		} catch (UnsupportedEncodingException e) {
			LogUtils.LOGE(TAG, "UnsupportedEncodingException");
			e.printStackTrace();
			result = null;
		} catch (ClientProtocolException e) {
			LogUtils.LOGE(TAG, "ClientProtocolException");
			e.printStackTrace();
			result = null;
		} catch (IOException e) {
			LogUtils.LOGE(TAG, "IOException");
			e.printStackTrace();
			result = null;
		} catch (Exception ex) {
			LogUtils.LOGE(TAG, "Exception");
			result = null;
		} finally {
			httpClient.getConnectionManager().shutdown();
		}

		return result;
	}

	private static DefaultHttpClient getThreadSafeClient(){
		DefaultHttpClient client = new DefaultHttpClient();
		ClientConnectionManager mgr = client.getConnectionManager();
		HttpParams params = client.getParams();
		client = new DefaultHttpClient(new ThreadSafeClientConnManager(params, mgr.getSchemeRegistry()), params);
		return client;
	}
}